package metrics

import (
	"github.com/rcrowley/go-metrics"
)

type PoolMetrics struct {
	BaseMetrics
	queueDelay  metrics.Timer
	queueReject metrics.Counter
	queueSize   metrics.Counter
	usage       metrics.Timer
	inUse       metrics.Counter
}

func (pm *PoolMetrics) Submitted() TimerContext {
	pm.queueSize.Inc(1)
	return NewInnerTimerContext(pm.queueDelay)
}

func (pm *PoolMetrics) Rejected(context TimerContext) {
	pm.queueSize.Dec(1)
	pm.queueReject.Inc(1)
	context.Stop()
}

func (pm *PoolMetrics) Begin(context TimerContext) TimerContext {
	pm.queueSize.Dec(1)
	pm.inUse.Inc(1)
	context.Stop()
	return NewInnerTimerContext(pm.usage)
}

func (pm *PoolMetrics) End(context TimerContext) {
	pm.inUse.Dec(1)
	context.Stop()
}

func NewPoolMetrics(registry metrics.Registry, baseName string, maxSize int) *PoolMetrics {
	pm := &PoolMetrics{
		BaseMetrics: BaseMetrics{
			BaseName: baseName,
			Registry: registry,
		},
	}

	pm.queueDelay = pm.Timer("queue-delay")
	pm.queueReject = pm.Counter("queue-reject")
	pm.queueSize = pm.Counter("queue-size")
	pm.usage = pm.Timer("usage")
	pm.inUse = pm.Counter("in-use")

	if maxSize > 0 {
		pm.Gauge(metrics.NewFunctionalGaugeFloat64(func() float64 {
			numerator := float64(pm.inUse.Count())
			denominator := float64(maxSize)
			return numerator / denominator
		}), "pool-ratio")

		pm.Gauge(metrics.NewFunctionalGauge(func() int64 {
			return int64(maxSize)
		}), "max-pool-size")
	}

	return pm
}
